﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using Micro.Core.ApiConsumer.ActionAttributes;
using Micro.Core.ApiConsumer.Context;
using Micro.Core.ApiConsumer.Extensions;
using Micro.Core.ApiConsumer.ParameterAttributes;
using Castle.DynamicProxy;
using Newtonsoft.Json;

namespace Micro.Core.ApiConsumer
{
    class ApiInterceptor : IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            var returnType = invocation.Method.ReturnType;
            var result = this.ExecuteApi(invocation);
            if (!invocation.Method.ReturnType.Name.Equals("Void"))
            {
                invocation.ReturnValue = Convert.ChangeType(result, returnType);
            }
        }

        /// <summary>
        /// 获取接口具体参数描述实例
        /// </summary>
        /// <param name="parameterInfo">参数详情</param>
        /// <param name="index">参数对应索引</param>
        /// <returns></returns>
        private ApiParameterDescriptor GetParameterDescriptor(ParameterInfo parameterInfo, int index)
        {
            return new ApiParameterDescriptor
            {
                Name = parameterInfo.Name,
                Index = index,
                ParameterAttribute = parameterInfo.GetAttributes<ApiParameterAttribute>(true).FirstOrDefault(),
                ParameterType = parameterInfo.ParameterType
            };
        }

        /// <summary>
        /// 构造api并执行请求
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns></returns>
        private string ExecuteApi(IInvocation invocation)
        {
            var cache = ApiDescriptorCache.GetApiActionDescriptor(invocation);
            var apiActionDescriptor = cache.Clone() as ApiActionDescriptor;
            for (int i = 0; i < apiActionDescriptor.Parameters.Length; i++)
            {
                apiActionDescriptor.Parameters[i].Value = invocation.GetArgumentValue(i);
            }

            var apiActionContext = new ApiActionContext
            {
                ActionDescriptor = apiActionDescriptor,
                Request = new HttpRequest()
            };

            return apiActionContext.Execute();
        }
    }
}
